/**
    MVP Tree data structure using graph database for I/O storage
    Copyright (C) 2014  David G. Starkweather

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    David Starkweather starkd88@gmail.com
**/

package org.phash.mvptree;

import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.index.IndexHits;
import org.neo4j.graphdb.index.IndexManager;
import org.neo4j.graphdb.Transaction;

/**
 * NodeFactory Implentation for a Datapoint
 * that stores a byte[]
 **/
public class BMBNodeFactoryImpl extends NodeFactory {

    /** constructor
     * @param storeDir String identifying dir for graph database
     * @param bf int value for branch factor of tree.
     * @param pl int value for path length of tree.
     * @param lc int value for max number of points in a leaf node.
     * @param nl int value for number of levels per node (no. vantage points)
     **/
    public BMBNodeFactoryImpl(String storeDir, int bf, int pl, int lc, int nl){

	super(storeDir, bf, pl, lc, nl);

    }

    /** constructor with default parameters 
     * @param storeDir directory for graphdb storage.
     **/
    public BMBNodeFactoryImpl(String storeDir){

	super(storeDir, 2, 5, 30, 2);

    }

    public Datapoint createDatapoint() {
	Node newNode;
	Transaction tx = graphdb.beginTx();
	try {
	    newNode = graphdb.createNode();
	    tx.success();
	}finally {
	    tx.finish();
	}

	return new BMBDatapoint(newNode);
    }

    protected Datapoint createDatapoint(Node node){
	return new BMBDatapoint(node);
    }

    public Datapoint lookupPoint(String id){
	IndexManager index =  graphdb.index();
	if (index != null){
	    Index<Node> nodeIndex = index.forNodes(DATAPOINTINDEX);
	    IndexHits<Node> hits = nodeIndex.get(POINTNAME,id);
	    Node node = hits.getSingle();
	    if (node != null) {
		return new BMBDatapoint(node);
	    }
	}
	return null;
    }


    public void deletePoint(String id) {
	/* remove point from index and mark node as inactive */
	IndexManager index = graphdb.index();
	if (index != null && index.existsForNodes(DATAPOINTINDEX)){	    
	    Index<Node> nodeIndex = index.forNodes(DATAPOINTINDEX);
	    IndexHits<Node> hits = nodeIndex.get(POINTNAME, id);
	    Node node = hits.getSingle();
	    if (node != null){
		Datapoint pnt = createDatapoint(node);
		Transaction tx = graphdb.beginTx();
		try {
		    nodeIndex.remove(node, POINTNAME, pnt.getId());
		    tx.success();
		}finally {
		    tx.finish();
		}
		pnt.setActive(false);
	    }
	}
	return;
    }

}
